import random
import re
import time
from typing import List

from sam import import_csv_path
from sam.app.bili.biliapi import get_video_detail
from sam.util.dbUtil import DB, mysql_env_config_dict
from sam.util.fileUtil2 import read_file, write_file_quick
from sam.util.httpUtil import get_web_driver
from sam.util.notifyUtil import work_we_chart_notify


class CollectVideoList(object):
    def __init__(self):
        super().__init__()
        self.db = DB(mysql_env_config_dict.get("net"), level="debug")
        self.browser = get_web_driver(headless=False, images_less=False)
        # https://search.bilibili.com/?from_source=web_search
        # https://www.bilibili.com/video/BV1y64y1R77Q?from=search&seid=14318793264604189141
        self.video_uuid_re = re.compile(r"video/(\w+)?")

    def __del__(self):
        if self.browser:
            self.browser.quit()
            print("无图浏览器退出")

    def login(self):
        self.browser.get("https://passport.bilibili.com/login")
        time.sleep(1)
        userName = self.browser.find_element_by_css_selector('#login-username')
        userName.send_keys("17090130391")
        password = self.browser.find_element_by_css_selector('#login-passwd')
        password.send_keys("mp@15037372431")
        submit = self.browser.find_element_by_css_selector('.btn-login')
        time.sleep(1)
        self.browser.execute_script("arguments[0].click();", submit)
        time.sleep(10)

    def extract_page_total_num(self):
        # page-item  搜索结果只有一页
        page_item_element_list = self.browser.find_elements_by_css_selector("div.page-wrap > div > ul > li.page-item")
        if not page_item_element_list:
            return 1
        # 搜索结果较多
        last_element_list = self.browser.find_elements_by_css_selector(
            "div.page-wrap > div > ul > li.page-item.last > button")
        if last_element_list:
            #     page-item
            page_total_num_str = self.browser.find_element_by_css_selector(
                "div.page-wrap > div > ul > li.page-item.last > button").text.strip()
            return int(page_total_num_str)
        else:
            # 搜索结果不多
            page_item_element_list = self.browser.find_elements_by_css_selector(
                "div.page-wrap > div > ul > li.page-item")
            last_element = page_item_element_list[-2]
            page_total_num_str = last_element.text.strip()
            return int(page_total_num_str)

    def extract_page_vide_info(self, keyword):
        item_list = []
        video_item_list = self.browser.find_elements_by_css_selector(".video-item")
        for video_item in video_item_list:
            video_info = video_item.find_element_by_css_selector(".info")

            title_div_element = video_info.find_element_by_css_selector("div.headline.clearfix")
            a_tag_element = title_div_element.find_element_by_css_selector("a.title")
            title = a_tag_element.get_attribute("title").strip()
            url = a_tag_element.get_property("href").strip()
            uuid = re.search(self.video_uuid_re, url).group(1)

            tags_div_element = video_info.find_element_by_css_selector("div.tags")
            watch_num_str = tags_div_element.find_element_by_css_selector("span.watch-num").text.strip()

            if "-" in watch_num_str:
                watch_num = 0
            elif "万" in watch_num_str:
                new_watch_num_str = watch_num_str.replace("万", '')
                watch_num = int(float(new_watch_num_str) * 10000)
            else:
                watch_num = int(watch_num_str)
            upload_date = tags_div_element.find_element_by_css_selector("span.time").text.strip()
            upper_name = tags_div_element.find_element_by_css_selector("a.up-name").text.strip()
            upper_home_page = tags_div_element.find_element_by_css_selector("a.up-name").get_property("href").strip()

            item_list.append(
                {
                    "keyword": keyword,
                    "title": title,
                    "url": url,
                    "uuid": uuid,
                    "watch_num": watch_num,
                    "upload_date": upload_date,
                    "upper_name": upper_name,
                    "upper_home_page": upper_home_page,
                }
            )
        if item_list:
            self.db.batch_update_by_item_list(
                item_list=item_list
                , table_name="bili_list"
                , optional="BatchInsert"
                , batch_size=20
            )

    def search_by_loop(self, keyword, page_total_num, next_page_num):
        while next_page_num <= page_total_num:
            print(f" 关键词: {keyword} 正在进行 {next_page_num}/{page_total_num} 页")
            page_url = f"https://search.bilibili.com/all?keyword={keyword}&from_source=web_search&order=click&duration=0&tids_1=3&page={next_page_num}"
            self.browser.get(page_url)
            self.extract_page_vide_info(keyword)
            next_page_num += 1
            return self.search_by_loop(keyword, page_total_num, next_page_num)
        else:
            print(f" 关键词: {keyword} 抓取完毕, 共 {page_total_num} 页")

    def search(self, keyword):
        # self.browser.get(f"https://search.bilibili.com/all?keyword={keywords}&from_source=web_search&order=click&duration=0&tids_1=3&page=2")
        index_page_url = f"https://search.bilibili.com/all?keyword={keyword}&from_source=web_search&order=click&duration=0&tids_1=3"
        self.browser.get(index_page_url)
        time.sleep(random.randint(3, 6))
        # 解析 总页数
        page_total_num = self.extract_page_total_num()
        if page_total_num:
            print(f" 关键词: {keyword} 正在进行 1/{page_total_num} 页")
            # 解析 当前页面的内容
            self.extract_page_vide_info(keyword)
            self.search_by_loop(keyword, page_total_num, next_page_num=2)
        else:
            work_we_chart_notify(f" 关键词： {keyword} 搜索结果 页数 过少， 暂且不爬取")

    def main(self):
        line_list = read_file(import_csv_path)
        # self.login()
        for line in line_list:
            keyword = line[0].strip()
            if keyword:
                print(f"将要抓取  关键词： {keyword}")
                self.search(keyword=keyword)
        else:
            print("全部已抓取完毕")
            work_we_chart_notify(f" 当前 批次的 关键词 爬取完了, {line_list[0][0]} -- {line_list[-1][0]}")


class CollectVideoDetail(object):
    def __init__(self):
        super().__init__()
        self.db = DB(mysql_env_config_dict.get("net"), level="debug")

    def fetch_bvid_list_by_keyword(self, keyword: str) -> List[str]:
        query_result_list = self.db.query(
            table_name="bili_list"
            , column_str="uuid"
            , where=f" keyword = '{keyword}'"
            , optional="tuple"
        )
        all_bvid_list = [query_result[0] for query_result in query_result_list]
        if all_bvid_list:
            exists_bvid_list = self.fetch_exists_bvid_list(all_bvid_list)
            return list(set(all_bvid_list).difference(set(exists_bvid_list)))
        else:
            return []

    def fetch_exists_bvid_list(self, bvid_list: List[str]) -> List[str]:
        uuid_str = "', '".join(bvid_list)
        query_result_list = self.db.query(
            table_name="bili_detail"
            , column_str="uuid"
            , where=f" uuid in ('{uuid_str}')  and comment_text != '' "
            , optional="tuple"
        )
        if query_result_list:
            return [query_result[0] for query_result in query_result_list if query_result]
        else:
            return []

    def main(self):
        un_bvid_list = []
        for keyword in [
            '少年', '起风了', '芒种', '成都', '野狼disco'
            , '凉凉', '海底', '生僻字', '大碗宽面', '热爱105°C的你'
        ]:
            bvid_list = self.fetch_bvid_list_by_keyword(keyword)
            for bvid in bvid_list:
                if bvid in ['BV1E84y1F7dr', 'BV1Jt411378g', 'BV1Hb411L71C', 'BV1V4411p7rE', 'BV144411t7X7']:
                    continue
                detail = get_video_detail(bvid)
                if detail and detail['comment_text']:
                    self.db.batch_update_by_item_list(
                        item_list=[detail]
                        , table_name="bili_detail"
                        # , optional="InsertOrUpdate"
                        , optional="BatchUpdate"
                        , batch_size=1
                        , condition={"in": "uuid"}
                    )
                    print(f"抓取成功的 bvid: {bvid} ")
                else:
                    print(f"抓取失败的 bvid: {bvid} ")
                    un_bvid_list.append([bvid])
            work_we_chart_notify(f" 关键词： {keyword} 爬取完毕")
        work_we_chart_notify("全部抓取完毕")
        write_file_quick(data_list=un_bvid_list)


if __name__ == "__main__":
    process = CollectVideoDetail()
    process.main()
